﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Rubik.Common;
using Rubik.Common.Operations;

namespace Viewer
{
    public partial class Form1 : Form
    {
        private static readonly IDictionary<int, Brush> brushes = new Dictionary<int, Brush>();

        private const int TileSize = 32;

        private readonly Cube cube = new Cube();

        static Form1()
        {
            brushes[0] = Brushes.Transparent;
            brushes[1] = Brushes.Yellow;
            brushes[2] = Brushes.Green;
            brushes[3] = Brushes.Orange;
            brushes[4] = Brushes.Blue;
            brushes[5] = Brushes.Black;
            brushes[6] = Brushes.Red;
        }

        public Form1()
        {
            cube.Initialize();

            InitializeComponent();

            clearButton.Click += ClearState;
            frontCw.Click += FrontCw;
            frontCCw.Click += Front2Cw;
            front3Cw.Click += Front3Cw;
            left1Cw.Click += Left1Cw;
            top1Cw.Click += Top1Cw;

            generateButton.Click += Generate;
        }

        private void Generate(object sender, EventArgs e)
        {
            CubeGenerator.Generate(cube);


            byte[][,] dump = cube.Dump();

            CubeDumpValidator validator = new CubeDumpValidator();
            validator.Validate(dump);

            Invalidate();
        }

        private void Top1Cw(object sender, EventArgs e)
        {
            ICubeOperation operation = new TopRotateClockwise(0);
            operation.Do(cube);
            Invalidate();
        }

        private void Left1Cw(object sender, EventArgs e)
        {
            ICubeOperation operation = new LeftRotateClockwise(0);
            operation.Do(cube);
            Invalidate();
        }

        private void Front3Cw(object sender, EventArgs e)
        {
            ICubeOperation operation = new FrontRotateClockwise(2);
            operation.Do(cube);
            Invalidate();
        }

        private void Front2Cw(object sender, EventArgs e)
        {
            ICubeOperation operation = new FrontRotateClockwise(1);
            operation.Do(cube);
            Invalidate();
        }

        private void FrontCw(object sender, EventArgs e)
        {
            ICubeOperation operation = new FrontRotateClockwise(0);
            operation.Do(cube);
            Invalidate();
        }

        private void ClearState(object sender, EventArgs e)
        {
            cube.Initialize();
        }

        private void DrawFacet(byte[,] facetData, Graphics graphics, int x, int y)
        {
            Pen pen = new Pen(Color.Gray);
            for (int i = 0; i <= facetData.GetUpperBound(0); i++)
            {
                for (int j = 0; j <= facetData.GetUpperBound(1); j++)
                {
                    //graphics.DrawRectangle(, x + i * TileSize, y + j * TileSize, TileSize, TileSize);
                    byte code = facetData[i, j];
                    graphics.FillRectangle(brushes[code],
                        x + 1 + (i * TileSize),
                        y + 1 + (j * TileSize),
                        TileSize - 2,
                        TileSize - 2);
                    graphics.DrawRectangle(pen,
                        x + (i * TileSize),
                        y + (j * TileSize),
                        TileSize - 1,
                        TileSize - 1);
                }
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            try
            {
                byte[][,] dump = cube.Dump();

                DrawFacet(dump[0], e.Graphics, 100, 20);
                DrawFacet(dump[1], e.Graphics, 4, 116);
                DrawFacet(dump[2], e.Graphics, 100, 116);
                DrawFacet(dump[3], e.Graphics, 196, 116);
                DrawFacet(dump[4], e.Graphics, 100, 212);
                DrawFacet(dump[5], e.Graphics, 100, 308);
            }
            catch (Exception)
            {
            }
        }
    }
}
